/**
 * @Author Puzzle
 * @Date 2022/6/13 4:22 下午
 **/

package service

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"time"
	"zsc-boot/app/system_layer/model"
	"zsc-boot/app/system_layer/model/request"
	"zsc-boot/core/orm"
)

var ServiceUsersService = new(serviceUsersService)

type serviceUsersService struct {
}

func (s *serviceUsersService) GetSubUserIds(ctx *gin.Context) []uint {
	userId := GetUserID(ctx)

	userIds := make([]uint, 0)

	userInfo, _ := orm.Detail[model.ServiceUser](userId, "Role")
	if userInfo.Role.Code == "root" {
		_ = orm.GetDb().Model(&model.ServiceUser{}).Pluck("id", &userIds).Error
		return userIds
	}

	userList := s.GetSubUsers(uint(userId))

	for _, user := range userList {
		userIds = append(userIds, user.ID)
	}
	return userIds
}

// GetSubUsers 获取下级
func (s *serviceUsersService) GetSubUsers(id uint) []model.ServiceUserSimple {
	//判断自已是否为部门负责人
	deps := make([]model.ServiceDepartment, 0)
	if err := orm.GetDb().Where("principal = ?", id).Preload("MembersList").
		Preload("Children.MembersList").
		Preload("Children.Children.MembersList").
		Preload("Children.Children.Children.MembersList").
		Find(&deps).Error; err != nil {
		return nil
	}

	subUsers := s.GetDepUsers(deps)
	//去重
	userMap := make(map[uint]model.ServiceUserSimple)
	for _, u := range subUsers {
		userMap[u.ID] = u
	}
	//回填
	subUsers = make([]model.ServiceUserSimple, 0, len(userMap))
	for _, u := range userMap {
		subUsers = append(subUsers, u)
	}
	subUsers = append(subUsers, model.ServiceUserSimple{ID: id})
	return subUsers
}

func (s *serviceUsersService) GetDepUsers(deps []model.ServiceDepartment) (userList []model.ServiceUserSimple) {
	for _, dep := range deps {
		userList = append(userList, dep.MembersList...)
		if len(dep.Children) > 0 {
			userList = append(userList, s.GetDepUsers(dep.Children)...)
		}
	}
	return
}

// GetUserInfo 用户详情
func (s *serviceUsersService) GetUserInfo(id uint) (user model.ServiceUser, err error) {
	err = orm.GetDb().Where("id = ?", id).
		Preload("DepInfo").Preload("Role").
		First(&user).Error

	user.SubUsers = s.GetSubUsers(id)
	return
}

func (s *serviceUsersService) GetUserListByDep(deps []model.ServiceDepartment) (userList []model.ServiceUserSimple) {
	for _, dep := range deps {
		userList = append(userList, dep.MembersList...)
		if len(dep.Children) > 0 {
			userList = append(userList, s.GetUserListByDep(dep.Children)...)
		}
	}
	return
}

// CreateUsers 创建用户
func (s *serviceUsersService) CreateUsers(user model.ServiceUser) (err error) {
	if !errors.Is(orm.GetDb().Where("mobile = ?", user.Mobile).First(&model.ServiceUser{}).Error, gorm.ErrRecordNotFound) { // 判断手机号是否已存在
		return errors.New("手机号已存在")
	}

	user.Password = s.MD5V([]byte(user.Password))
	user.Login = user.Mobile
	// 创建用户
	err = orm.GetDb().Create(&user).Error
	return
}

// DeleteServiceUsers 删除用户
func (s *serviceUsersService) DeleteServiceUsers(user model.ServiceUser) (err error) {
	return orm.GetDb().Transaction(func(tx *gorm.DB) error {
		if err = tx.Delete(&user).Error; err != nil {
			return err
		}

		var userCustomerList []model.UserCustomer
		if err = tx.Where("user_id = ?", user.ID).
			Find(&userCustomerList).Error; err != nil {
			return err
		}
		//构建流转日志
		flowLogList := make([]model.CustomerFlowLog, 0, len(userCustomerList))
		for _, u := range userCustomerList {
			flowLogList = append(flowLogList, model.CustomerFlowLog{
				OldUserId:  u.UserId,
				NewUserId:  0,
				Reason:     "员工删除掉入公海",
				CustomerId: u.ID,
			})
		}
		if len(flowLogList) > 0 {
			if err = tx.Create(&flowLogList).Error; err != nil {
				return err
			}
		}

		return tx.Table("customer").Where("user_id = ?", user.ID).
			Update("user_id", 0).Error
	})
}

// UpdateServiceUsers 更新用户
func (s *serviceUsersService) UpdateServiceUsers(user request.UpdateUserReq) (err error) {
	user.Login = user.Mobile
	if !errors.Is(orm.GetDb().Where("login = ? AND id != ?", user.Login, user.ID).First(&model.ServiceUser{}).Error, gorm.ErrRecordNotFound) { // 判断用户名是否注册
		return errors.New("帐号已存在")
	}
	if !errors.Is(orm.GetDb().Where("mobile = ? AND id != ?", user.Mobile, user.ID).First(&model.ServiceUser{}).Error, gorm.ErrRecordNotFound) { // 判断手机号是否已存在
		return errors.New("手机号已存在")
	}
	data := map[string]any{
		"name":         user.Name,
		"ident_number": user.IdentNumber,
		"mobile":       user.Mobile,
		"is_active":    user.IsActive,
		"role_id":      user.RoleId,
		"service_date": user.ServiceDate,
		"day_cap":      user.DayCap,
		"customer_cap": user.CustomerCap,
		//"city":         user.City,
	}
	if user.DepId != nil {
		data["dep_id"] = *user.DepId
	}
	if user.City != "" {
		data["city"] = user.City
	}
	return orm.GetDb().Model(&model.ServiceUser{}).Omit("created_at, password").Where("id = ?", user.ID).Updates(data).Error
}

func (s *serviceUsersService) AddLoginLog(user model.ServiceUser, isError bool, msg, ip string) {
	_ = orm.GetDb().Create(&model.LogLogin{
		Name:    user.Name,
		UserId:  user.ID,
		IsError: isError,
		Msg:     msg,
		Ip:      ip,
	})
}

// GetServiceUsersList 获取用户列表
func (s *serviceUsersService) GetServiceUsersList(info request.ServiceUsersSearch, ctx *gin.Context) (
	err error, list []model.ServiceUser, total int64, dayCap int64, todayLen int64) {

	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)

	userId := GetUserID(ctx)
	userInfo, err := orm.Detail[model.ServiceUser](userId, "Role")
	if err != nil {
		return
	}

	db := orm.GetDb().Model(&model.ServiceUser{})
	if userInfo.Role.Code != "root" {
		userIds := s.GetSubUserIds(ctx)
		if userIds == nil || len(userIds) == 0 {
			userIds = []uint{0}
		}
		db = db.Where("id in ?", userIds)
	}
	if info.Name != "" {
		db = db.Where("name like ?", "%"+info.Name+"%")
	}
	if info.Mobile != "" {
		db = db.Where("mobile like ?", "%"+info.Mobile+"%")
	}
	if info.IsActive != nil {
		db = db.Where("is_active = ?", info.IsActive)
	}

	//创建时间
	if info.StartDate != "" {
		db = db.Where("created_at >= ?", info.StartDate+" 00:00:00")
	}
	if info.EndDate != "" {
		db = db.Where("created_at <= ?", info.EndDate+" 23:59:59")
	}
	if info.DepId != 0 {
		db = db.Where("dep_id = ?", info.DepId)
	}
	err = db.Count(&total).Error

	if total == 0 {
		return
	}

	if err = db.Session(&gorm.Session{}).Select("sum(day_cap)").Scan(&dayCap).Error; err != nil {
		return
	}
	if err = db.Session(&gorm.Session{}).Select("sum(today_len)").Scan(&todayLen).Error; err != nil {
		return
	}

	err = db.Order("dep_id desc").
		Preload("DepInfo").
		Limit(limit).Offset(offset).Preload("Role").
		Find(&list).Error

	userIds := make([]uint, 0)
	for _, v := range list {
		userIds = append(userIds, v.ID)
	}

	var group []struct {
		UserId     uint
		CustomerId uint
	}
	orm.GetDb().Table("customer_follow_log").
		Where("created_at > ? and user_id in ?", time.Now().Format(time.DateOnly), userIds).
		Distinct("user_id,customer_id").Find(&group)

	for _, v := range group {
		for k, _ := range list {
			if list[k].ID == v.UserId {
				list[k].FollowNum++
			}
		}
	}
	return err, list, total, dayCap, todayLen
}

// GetUserDropDownBox 获取用户下拉框
func (s *serviceUsersService) GetUserDropDownBox(info request.ServiceUsersSearch, userInfo model.ServiceUser) (err error, list interface{}, total int64) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	var serviceUsersList []model.ServiceUserSimple

	db := orm.GetDb().Model(&model.ServiceUser{})
	if info.Name != "" {
		db.Where("name like ?", "%"+info.Name+"%")
	}
	if userInfo.Role.Code != "root" {
		userInfoList := s.GetSubUsers(userInfo.ID)
		userIds := make([]uint, 0, len(userInfoList))
		for _, user := range userInfoList {
			userIds = append(userIds, user.ID)
		}
		db.Where("id in (?)", userIds)
	}

	if info.NotDep {
		db.Where("dep_id = ?", 0)
	}

	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Limit(limit).Offset(offset).Find(&serviceUsersList).Error
	return err, serviceUsersList, total
}

// UpdatePassword 修改用户密码
func (s *serviceUsersService) UpdatePassword(ID uint, password string) (err error) {
	err = orm.GetDb().Model(&model.ServiceUser{}).Where("id = ?", ID).Update("password", s.MD5V([]byte(password))).Error
	return err
}

// MD5V 密码 md5 加密
func (s *serviceUsersService) MD5V(str []byte, b ...byte) string {
	h := md5.New()
	h.Write(str)
	return hex.EncodeToString(h.Sum(b))
}

// OldToNewPassword 修改密码
func (s *serviceUsersService) OldToNewPassword(updatePasswordReq1 request.OldToNewResp) (err error) {
	var ServiceUsers model.ServiceUser
	orm.GetDb().Where("id = ?", updatePasswordReq1.ID).First(&ServiceUsers)

	if ServiceUsers.Password == s.MD5V([]byte(updatePasswordReq1.OldPassword)) {
		err = orm.GetDb().Model(&ServiceUsers).Where("id = ?", updatePasswordReq1.ID).Update("password", s.MD5V([]byte(updatePasswordReq1.NewPassword))).Error
		return err
	} else {
		return errors.New("旧密码错误")
	}
}
